/*
 * uart.c
 *
 *  Created on: Sep 19, 2013
 *      Author: Ken Arok
 */

#include "config_board.h"

#if BOARD_2_1_USED

#include <avr/io.h>
#include "sysclk.h"
#include "timers_hw.h"
#include "uart.h"

#define UART0				0
#define UART1				1

#define PARITY_MASK_BIT		0x30
#define STOPBIT_MASK_BIT	0x08

/* Flag to indicate waiting frame. */
static volatile bool uart0_wait_recv_frame = false, uart1_wait_recv_frame = false;

/* Receive timeout value in milisecond. */
static volatile uint32_t *_tmr_recv_uart0 = NULL;
static volatile uint32_t *_tmr_recv_uart1 = NULL;
static uint32_t receive_timeout[2] = {2400, 2400};

/* Interrupt flag utilities */
static bool tx_interrupt_is_used[2] = {0, 0};
static bool rx_interrupt_is_used[2] = {0, 0};

/* Pointer to the data byte transmit buffer. */
static const volatile uint8_t  *uart_tx0_data_byte = NULL;
static const volatile uint8_t  *uart_tx1_data_byte = NULL;

/* Pointer to the data word transmit buffer. */
static const volatile uint16_t  *uart_tx0_data_word = NULL;
static const volatile uint16_t  *uart_tx1_data_word = NULL;

/* Pointer to the data byte receive buffer. */
static volatile uint8_t *uart_rx0_data_byte = NULL;
static volatile uint8_t *uart_rx1_data_byte = NULL;

/* Pointer to the data word receive buffer. */
static volatile uint16_t *uart_rx0_data_word = NULL;
static volatile uint16_t *uart_rx1_data_word = NULL;

/* Remaining number of data to transmit. */
static volatile uint32_t uart_tx0_nb_count = 0;
static volatile uint32_t uart_tx1_nb_count = 0;

/* Total number of data to receive. */
static volatile uint32_t uart_rx0_nb_received = 0;
static volatile uint32_t uart_rx1_nb_received = 0;

/* Remaining number of data to receive. */
static volatile uint32_t uart_rx0_nb_count = 0;
static volatile uint32_t uart_rx1_nb_count = 0;

/* Bit length bigger than 8-bit. */
static bool datawidth0_is_bigger8bit = false;
static bool datawidth1_is_bigger8bit = false;

/* Internal signaling for transmitter receiver. */
static volatile bool xUART0Semaphore = true, xUART1Semaphore = true;

/* Global signaling to wake up higher task. */
volatile bool xUART0Signaling = false, xUART1Signaling = false;


/* Function of received signaling. */
static TimerFuncVoid_t _funcRecvSignaling0, _funcRecvSignaling1;



/** \brief Initialize serial UART.
 */
static void uart0_init(void);
static void uart1_init(void);

/* \brief UART 0 Receive Interrupt Handler.
 */
static void uart0_recv_interrupt_handler(void);

/* \brief UART 1 Receive Interrupt Handler.
 */
static void uart1_recv_interrupt_handler(void);

/* \brief UART 0 Ready to transmit interrupt handler.
 */
static void uart0_ready_transmit_interrupt_handler(void);

/* \brief UART 1 Ready to transmit interrupt handler.
 */
static void uart1_ready_transmit_interrupt_handler(void);

/* \brief UART 0 Transmit complete interrupt handler.
 */
static void uart0_transmit_complete_interrupt_handler(void);

/* \brief UART 0 Transmit complete interrupt handler.
 */
static void uart1_transmit_complete_interrupt_handler(void);

/* \brief Set asynchronus baudrate for UART.
 *
 * \param _uart	 	UART number.
 * \param _baudrate	Desired baudrate.
 */
static void uart_set_async_baudrate(uint8_t _uart, uint32_t _baudrate);

/** \brief Start transmit data out to the port.
 *  \param _xPort					Serial Port Number.
 *  \param _ptrData					Pointer to data buffer want to be transmitted.
 *  \param _size_t					Number of byte/word to be transmitted.
 *  \param _datawidth8bitmore		true = word transfer, false = byte transfer.
 *  \retval UART_STATUS_OK			Transmit is already started.
 *  \retval UART_ERR_INVALID_ARG	Selected Port is invalid, transmit cannot be started.
 *  \retval UART_ERR_TIMEOUT		Transmission timeout.
 */
static uart_status_code_t uart_write_start(COM_port_t _xPort, const void *_ptrData, uint32_t _size_t, bool _datawidth8bitmore);

/** \brief Start receive data from the port.
 *  \param _xPort					Serial Port Number.
 *  \param _pbuf					Pointer to receiver buffer.
 *  \param _size					Number of byte/word to be received.
 *  \param _pRecvSize				Pointer to variable counting byte/word received.
 *  \param _datawidth8bitmore		true = word transfer, false = byte transfer.
 *  \retval UART_STATUS_OK			Transmit is already started.
 *  \retval UART_ERR_INVALID_ARG	Selected Port is invalid, transmit cannot be started.
 */
static uart_status_code_t uart_read_start(COM_port_t _xPort, void *_pbuf, uint32_t _size_t, uint32_t *_pRecvSize, bool _datawidth8bitmore);

/** \brief Issue UART 0 received complete signal.
 *
 * \param _tmr	Pointer to timer;
 *
 */
static void prvRecvIssueSignal0(void *_tmr);

/** \brief Issue UART 1 received complete signal.
 *
 * \param _tmr	Pointer to timer;
 *
 */
static void prvRecvIssueSignal1(void *_tmr);

/* ------------------------------------------------------------------------------------ */

/* UART 0 Interrupt Receive Complete. */
ISR(USART0_RXC_vect)
{
	uart0_recv_interrupt_handler();
}

/* UART 1 Interrupt Receive Complete. */
ISR(USART1_RXC_vect)
{
	uart1_recv_interrupt_handler();
}


/* UART 0 Interrupt Data Register Empty. */
ISR(USART0_UDRE_vect)
{
	uart0_ready_transmit_interrupt_handler();
}

/* UART 1 Interrupt Data Register Empty. */
ISR(USART1_UDRE_vect)
{
	uart1_ready_transmit_interrupt_handler();
}

/* UART 0 Interrupt Transmit Complete. */
ISR(USART0_TXC_vect)
{
	uart0_transmit_complete_interrupt_handler();
}

/* UART 0 Interrupt Transmit Complete. */
ISR(USART1_TXC_vect)
{
	uart1_transmit_complete_interrupt_handler();
}


uart_status_code_t uart_open(COM_port_t _xPort, const uint8_t _flag)
{
	uart_status_code_t _ret_status = UART_STATUS_OK;

	switch(_xPort) {
		case serCOM1:
			/* Force close. */
			if(_flag == 2) {
				xUART0Semaphore = true;
			}
			if(xUART0Semaphore == true) {
				xUART0Semaphore = false;
			}
		break;

		case serCOM2:
			/* Force close. */
			if(_flag == 2) {
				xUART1Semaphore = true;
			}
			if(xUART1Semaphore == true) {
				xUART1Semaphore = false;
			}
		break;

		default:
			_ret_status = UART_ERR_INVALID_ARG;
		break;
	}

	return _ret_status;
}


void uart_close(COM_port_t _xPort)
{
	switch(_xPort) {
		case serCOM1:
			while(xUART0Semaphore == false);
			xUART0Semaphore = true;
		break;

		case serCOM2:
			while(xUART1Semaphore == false);
			xUART1Semaphore = true;
		break;

		default: break;
	}
}

uart_status_code_t uart_write_word(COM_port_t _xPort, const void *_pPacket, uint32_t _size_t)
{
	/* Protect unpredicted behavior if argument is NULL pointer */
	if(_pPacket == NULL) return UART_ERR_INVALID_ARG;

	/* Start send data. */
	return uart_write_start(_xPort, _pPacket, _size_t, true);
}

uart_status_code_t uart_write_byte(COM_port_t _xPort, const void *_pPacket, uint32_t _size_t)
{
	/* Protect unpredicted behavior if argument is NULL pointer */
	if(_pPacket == NULL) return UART_ERR_INVALID_ARG;

	/* Start send data. */
	return uart_write_start(_xPort, _pPacket, _size_t, false);
}


uart_status_code_t uart_read_word(COM_port_t _xPort, void *_pRxBuff, uint32_t _size_t, uint32_t *_pRcvdSize)
{
	/* Protect unpredicted behavior if argument is NULL pointer */
	if(_pRxBuff == NULL) return UART_ERR_INVALID_ARG;

	/* Start capturing data. */
	uart_read_start(_xPort, _pRxBuff, _size_t, _pRcvdSize, true);

	return UART_STATUS_OK;
}


uart_status_code_t uart_read_byte(COM_port_t _xPort, void *_pRxBuff, uint32_t _size_t, uint32_t *_pRcvdSize)
{
	/* Protect unpredicted behavior if argument is NULL pointer */
	if(_pRxBuff == NULL) return UART_ERR_INVALID_ARG;

	/* Start capturing data. */
	uart_read_start(_xPort, _pRxBuff, _size_t, _pRcvdSize, false);

	return UART_STATUS_OK;
}


void uart_init(void)
{
	/* Initialize UART option to default setting */
	uart0_init();
	uart1_init();
}


void uart_setup(COM_port_t _xPort, const uart_options_t *_opt)
{
	switch(_xPort) {
		case serCOM1:
			/* Setup parity. */
			UCSR0C &= ~PARITY_MASK_BIT;
			UCSR0C |= _opt->paritytype;
			/* Setup stop bit. */
			UCSR0C &= ~STOPBIT_MASK_BIT;
			UCSR0C |= _opt->stopbits;
			/* Setup data bit. */
			if(_opt->charlength > 0x06) {
				UCSR0B |= (1 << UCSZ02);
				UCSR0C |= UART_8_DATABIT;
			}
			else {
				UCSR0B &= ~(1 << UCSZ02);
				UCSR0C |= UART_8_DATABIT;
			}
			/* Setup baudrate. */
			uart_set_async_baudrate(UART0, _opt->baudrate);
		break;

		case serCOM2:
			/* Setup parity. */
			UCSR1C &= ~PARITY_MASK_BIT;
			UCSR1C |= _opt->paritytype;
			/* Setup stop bit. */
			UCSR1C &= ~STOPBIT_MASK_BIT;
			UCSR1C |= _opt->stopbits;
			/* Setup data bit. */
			if(_opt->charlength > 0x06) {
				UCSR1B |= (1 << UCSZ12);
				UCSR1C |= UART_8_DATABIT;
			}
			else {
				UCSR1B &= ~(1 << UCSZ12);
				UCSR1C |= UART_8_DATABIT;
			}
			/* Setup baudrate. */
			uart_set_async_baudrate(UART1, _opt->baudrate);
		break;

		default: break;
	}
}


void uart_tranfer_mode(COM_port_t _xPort, uart_transfer_mode_flag_t _flag)
{
	switch(_xPort) {
		case serCOM1:
		case serCOM2:
			switch(_flag) {
				case UART_POLLED:
					tx_interrupt_is_used[_xPort] = false;
					rx_interrupt_is_used[_xPort] = false;
				break;

				case UART_POLLED_TX:
					tx_interrupt_is_used[_xPort] = false;
					rx_interrupt_is_used[_xPort] = true;
				break;

				case UART_POLLED_RX:
					tx_interrupt_is_used[_xPort] = true;
					rx_interrupt_is_used[_xPort] = false;
				break;

				case UART_INTERRUPT:
					tx_interrupt_is_used[_xPort] = true;
					rx_interrupt_is_used[_xPort] = true;
				break;

				default: break;
			}
		break;

		default: break;
	}
}


void uart_rx_timeout(COM_port_t _xPort, const uint32_t _to_ms)
{

	switch(_xPort) {
		case serCOM1:
		case serCOM2:
			if(_to_ms) {
				receive_timeout[_xPort] = _to_ms;
			}
		break;

		default: break;
	}
}

/* ------------------------------------------------------------------------------------- */

static void uart0_recv_interrupt_handler(void)
{
	uint8_t _status;
	uint16_t _data;

	_status = UCSR0A;
	/* Reload Timer. */
	*_tmr_recv_uart0 = receive_timeout[0];

	/* Check if any error. */
	if(_status & 0x1C) {
		/* Clear receiver buffer. */
		_data = UDR0;
	}
	/* Process the received character. */
	else {
		if(uart_rx0_nb_count > 0) {
			/* Now, it is not waiting anymore. */
			uart0_wait_recv_frame = false;
			/* Decrease remaining number data to receive. */
			uart_rx0_nb_count--;

			if(datawidth0_is_bigger8bit == true) {
				if(uart_rx0_data_word != NULL) {
					/* Get the data from receiver buffer. */
					_data = (UCSR0B & 0x02) >> 1;
					_data = _data << 8;
					_data = _data | (uint16_t)UDR0;
					/* Copy data to receiver buffer. */
					*uart_rx0_data_word = _data;
					/* Increase pointer of receiver data buffer. */
					uart_rx0_data_byte++;
					/* Increase received byte number. */
					uart_rx0_nb_received++;
				}
			}
			else {
				if(uart_rx0_data_byte != NULL) {
					/* Get the data from receiver buffer. */
					_data = UDR0;
					/* Copy data to receiver buffer. */
					*uart_rx0_data_byte = _data;
					/* Increase pointer of receiver data buffer. */
					uart_rx0_data_byte++;
					/* Increase received byte number. */
					uart_rx0_nb_received++;
				}
			}
		}
		else {
			/* Disable receive interrupt. */
			UCSR0B &= ~(1 << RXCIE0);
			/* Internal Signaling. */
			xUART0Semaphore = true;
		}
	}
}

static void uart1_recv_interrupt_handler(void)
{
	uint8_t _status;
	uint16_t _data;

	_status = UCSR1A;
	/* Reload Timer. */
	*_tmr_recv_uart1 = receive_timeout[1];

	/* Check if any error. */
	if(_status & 0x1C) {
		/* Clear receiver buffer. */
		_data = UDR1;
	}
	/* Process the received character. */
	else {
		if(uart_rx1_nb_count > 0) {
			/* Now, it is not waiting anymore. */
			uart1_wait_recv_frame = false;
			/* Decrease remaining number data to receive. */
			uart_rx1_nb_count--;

			if(datawidth1_is_bigger8bit == true) {
				if(uart_rx1_data_word != NULL) {
					/* Get the data from receiver buffer. */
					_data = (UCSR1B & 0x02) >> 1;
					_data = _data << 8;
					_data = _data | (uint16_t)UDR1;
					/* Copy data to receiver buffer. */
					*uart_rx1_data_word = _data;
					/* Increase pointer of receiver data buffer. */
					uart_rx1_data_byte++;
					/* Increase received byte number. */
					uart_rx1_nb_received++;
				}
			}
			else {
				if(uart_rx1_data_byte != NULL) {
					/* Get the data from receiver buffer. */
					_data = UDR1;
					/* Copy data to receiver buffer. */
					*uart_rx1_data_byte = _data;
					/* Increase pointer of receiver data buffer. */
					uart_rx1_data_byte++;
					/* Increase received byte number. */
					uart_rx1_nb_received++;
				}
			}
		}
		else {
			/* Disable receive interrupt. */
			UCSR1B &= ~(1 << RXCIE1);
			/* Internal Signaling. */
			xUART1Semaphore = true;
		}
	}
}


static void uart0_ready_transmit_interrupt_handler(void)
{
	/* No more data to transmit. */
	if(uart_tx0_nb_count == 0) {
		/* Finish the transmit operation. */
		UCSR0B &= ~(1 << UDRIE0);
	}
	else {
		if(datawidth0_is_bigger8bit == true) {
			/* Send data to transmit data register. */
			UCSR0B &= ~(1 << TXB80);
			UCSR0B |= (*uart_tx0_data_word >> 8) & 0x01;
			UDR0 = (uint8_t)*uart_tx0_data_word;
			/* Increase the pointer of transmitter data buffer. */
			uart_tx0_data_word++;
		}
		else {
			/* Send data to transmit data register. */
			UDR0 = *uart_tx0_data_byte;
			/* Increase the pointer of transmitter data buffer. */
			uart_tx0_data_byte++;
		}

		/* Decrease transmitted word number. */
		uart_tx0_nb_count--;
	}
}


static void uart1_ready_transmit_interrupt_handler(void)
{
	/* No more data to transmit. */
	if(uart_tx1_nb_count == 0) {
		/* Finish the transmit operation. */
		UCSR1B &= ~(1 << UDRIE1);
	}
	else {
		if(datawidth1_is_bigger8bit == true) {
			/* Send data to transmit data register. */
			UCSR1B &= ~(1 << TXB81);
			UCSR1B |= (*uart_tx1_data_word >> 8) & 0x01;
			UDR1 = (uint8_t)*uart_tx1_data_word;
			/* Increase the pointer of transmitter data buffer. */
			uart_tx1_data_word++;
		}
		else {
			/* Send data to transmit data register. */
			UDR1 = *uart_tx1_data_byte;
			/* Increase the pointer of transmitter data buffer. */
			uart_tx1_data_byte++;
		}

		/* Decrease transmitted word number. */
		uart_tx1_nb_count--;
	}
}


static void uart0_transmit_complete_interrupt_handler(void)
{
	/* Disable interrupt. */
	UCSR0B &= ~(1 << TXCIE0);
	/* Internal Signaling. */
	xUART0Semaphore = true;
}


static void uart1_transmit_complete_interrupt_handler(void)
{
	/* Disable interrupt. */
	UCSR1B &= ~(1 << TXCIE1);
	/* Internal Signaling. */
	xUART1Semaphore = true;
}


static void uart0_init(void)
{
	xUART0Semaphore = false;
	/* Asynchronous operation. */
	UCSR0C &= ~(1 << UMSEL0);
	/* No paraity for default. */
	UCSR0C &= ~PARITY_MASK_BIT;
	UCSR0C |= UART_NO_PARITY;
	/* 1 Stop bit for default. */
	UCSR0C &= ~STOPBIT_MASK_BIT;
	UCSR0C |= UART_1_STOPBIT;
	/* 8 Data bit for default. */
	UCSR0B &= ~(1 << UCSZ02);
	UCSR0C |= UART_8_DATABIT;

	UCSR0C &= ~(1 << UCPOL0);

	/* Set baudrate 9600 for default. */
	uart_set_async_baudrate(UART0, 9600);

	/* Enable RX and TX. */
	UCSR0B |= (1 << RXEN0);
	UCSR0B |= (1 << TXEN0);

	_tmr_recv_uart0 = vTimer10msTake();
	if(_tmr_recv_uart0 == NULL) {
		while(1);
	}
}


static void uart1_init(void)
{
	xUART1Semaphore = false;
	/* Asynchronous operation. */
	UCSR1C &= ~(1 << UMSEL1);
	/* No paraity for default. */
	UCSR1C &= ~PARITY_MASK_BIT;
	UCSR1C |= UART_NO_PARITY;
	/* 1 Stop bit for default. */
	UCSR1C &= ~STOPBIT_MASK_BIT;
	UCSR1C |= UART_1_STOPBIT;
	/* 8 Data bit for default. */
	UCSR1B &= ~(1 << UCSZ12);
	UCSR1C |= UART_8_DATABIT;

	UCSR1C &= ~(1 << UCPOL1);

	/* Set baudrate 9600 for default. */
	uart_set_async_baudrate(UART1, 9600);

	/* Enable RX and TX. */
	UCSR1B |= (1 << RXEN1);
	UCSR1B |= (1 << TXEN1);

	_tmr_recv_uart1 = vTimer10msTake();
	if(_tmr_recv_uart1 == NULL) {
		while(1);
	}
}


static void uart_set_async_baudrate(uint8_t _uart, uint32_t _baudrate)
{
	uint32_t _fcpu;
	uint16_t _baudreg;

	switch(_uart) {
		case UART0:
			_fcpu = sysclk_get_cpu_hz();
			_baudreg = (_fcpu / (16 * _baudrate)) - 1;
			UBRR0H = (_baudreg >> 8) & 0x0F;
			UBRR0L = (uint8_t)_baudreg;
		break;

		case UART1:
			_fcpu = sysclk_get_cpu_hz();
			_baudreg = (_fcpu / (16 * _baudrate)) - 1;
			UBRR1H = (_baudreg >> 8) & 0x0F;
			UBRR1L = (uint8_t)_baudreg;
		break;

		default: break;
	}
}

static uart_status_code_t uart_write_start(COM_port_t _xPort, const void *_ptrData, uint32_t _size_t, bool _datawidth8bitmore)
{
	if(_xPort == serCOM1) {
		/* Get the length to be transmitted. */
		uart_tx0_nb_count = _size_t;
		/* Check data width. */
		if(_datawidth8bitmore == true) {
			/* Get the pointer of data. */
			uart_tx0_data_word = (const volatile uint16_t *)_ptrData;
		}
		else {
			/* Get the pointer of data. */
			uart_tx0_data_byte = (const volatile uint8_t *)_ptrData;
		}
		datawidth0_is_bigger8bit = _datawidth8bitmore;

		if (tx_interrupt_is_used[_xPort] == true) {
			/* Enable Transmit Interrupt. */
			UCSR0B |= (1 << TXCIE0);
			UCSR0B |= (1 << UDRIE0);
		}
		else {
			while(uart_tx0_nb_count) {
				/* Wait transmit data register ready. */
				while(!(UCSR0A & (1 << UDRE0)));

				if(datawidth0_is_bigger8bit == true) {
					/* Send data to transmit data register. */
					UCSR0B &= ~(1 << TXB80);
					UCSR0B |= (*uart_tx0_data_word >> 8) & 0x01;
					UDR0 = (uint8_t)*uart_tx0_data_word;
					/* Increase Pointer data. */
					uart_tx0_data_word++;
				}
				else {
					/* Send data to transmit data register. */
					UDR0 = *uart_tx0_data_byte;
					/* Increase Pointer data. */
					uart_tx0_data_byte++;
				}
				/* Decrease number word/byte counting. */
				uart_tx0_nb_count--;
			}

			/* Wait until transmission complete. */
			while(!(UCSR0A & (1 << TXC0)));

			/* Release Semaphore. */
			xUART0Semaphore = true;
		}
	}
	else if(_xPort == serCOM2) {
		/* Get the length to be transmitted. */
		uart_tx1_nb_count = _size_t;
		/* Check data width. */
		if(_datawidth8bitmore == true) {
			/* Get the pointer of data. */
			uart_tx1_data_word = (const volatile uint16_t *)_ptrData;
		}
		else {
			/* Get the pointer of data. */
			uart_tx1_data_byte = (const volatile uint8_t *)_ptrData;
		}
		datawidth1_is_bigger8bit = _datawidth8bitmore;

		if (tx_interrupt_is_used[_xPort] == true) {
			/* Enable Transmit Interrupt. */
			UCSR1B |= (1 << TXCIE1);
			UCSR1B |= (1 << UDRIE1);
		}
		else {
			while(uart_tx1_nb_count) {
				/* Wait transmit data register ready. */
				while(!(UCSR1A & (1 << UDRE1)));

				if(datawidth1_is_bigger8bit == true) {
					/* Send data to transmit data register. */
					UCSR1B &= ~(1 << TXB81);
					UCSR1B |= (*uart_tx1_data_word >> 8) & 0x01;
					UDR1 = (uint8_t)*uart_tx1_data_word;
					/* Increase Pointer data. */
					uart_tx1_data_word++;
				}
				else {
					/* Send data to transmit data register. */
					UDR1 = *uart_tx1_data_byte;
					/* Increase Pointer data. */
					uart_tx1_data_byte++;
				}
				/* Decrease number word/byte counting. */
				uart_tx1_nb_count--;
			}

			/* Wait until transmission complete. */
			while(!(UCSR1A & (1 << TXC1)));

			/* Release Semaphore. */
			xUART1Semaphore = true;
		}
	}
	else {
		return UART_ERR_INVALID_ARG;
	}

	return UART_STATUS_OK;
}


static uart_status_code_t uart_read_start(COM_port_t _xPort, void *_pbuf, uint32_t _size_t, uint32_t *_pRecvSize, bool _datawidth8bitmore)
{
	uint16_t _data;

	if(_xPort == serCOM1) {
		/* Set busy. */
		xUART0Signaling = false;
		/* Set infinite for receiver timer. */
		*_tmr_recv_uart0 = 0xFFFFFFFF;
		if(_datawidth8bitmore == true) {
			/* Update receiving buffer */
			uart_rx0_data_word = (volatile uint16_t *)_pbuf;
		}
		else {
			/* Update receiving buffer */
			uart_rx0_data_byte = (volatile uint8_t *)_pbuf;
		}
		uart0_wait_recv_frame = true;
		uart_rx0_nb_received = 0;
		_pRecvSize = (uint32_t *)&uart_rx0_nb_received;
		uart_rx0_nb_count = _size_t;
		datawidth0_is_bigger8bit = _datawidth8bitmore;

		if (rx_interrupt_is_used[_xPort] == true) {
			/* Set receiver timeout. */
			*_tmr_recv_uart0 = receive_timeout[0];
			_funcRecvSignaling0 = &prvRecvIssueSignal0;
			vTimer10msFuncReg(_funcRecvSignaling0, (void *)_tmr_recv_uart0);

			/* Enable Receive Interrupt. */
			UCSR0B |= (1 << RXCIE0);
		}
		else {
			*_tmr_recv_uart0 = receive_timeout[0];
			while(uart_rx0_nb_count && *_tmr_recv_uart0) {
				/* Wait incoming character. Do not block peripheral. */
				*_tmr_recv_uart0 = receive_timeout[0];
				while(!(UCSR0A & (1 << RXC0)) && *_tmr_recv_uart0);

				if (*_tmr_recv_uart0) {
					/* Check error receiving. */
					if(UCSR0A & 0x1C) {
						/* Clear receive buffer. */
						_data = UDR0;
					}
					else {
						/* Decrease remaining number data to receive. */
						uart_rx0_nb_count--;

						if(datawidth0_is_bigger8bit == true) {
							if(uart_rx0_data_word != NULL) {
								/* Get the data from receiver register. */
								_data = (UCSR0B & 0x02) >> 1;
								_data = _data << 8;
								_data = _data | (uint16_t)UDR0;
								/* Copy data to receiver buffer. */
								*uart_rx0_data_word = _data;
								/* Increase pointer of receiver data buffer. */
								uart_rx0_data_word++;
								/* Increase received word number. */
								uart_rx0_nb_received++;
							}
						}
						else {
							if(uart_rx0_data_byte != NULL) {
								/* Get the data from receiver register. */
								_data = UDR0;
								/* Copy data to receiver buffer. */
								*uart_rx0_data_byte = (uint8_t)_data;
								/* Increase pointer of receiver data buffer. */
								uart_rx0_data_byte++;
								/* Increase received byte number. */
								uart_rx0_nb_received++;
							}
						}
					}
				}
			}

			/* Release semaphore. */
			xUART0Semaphore = true;
			xUART0Signaling = true;
		}
	}
	else if(_xPort == serCOM2) {
		/* Set busy. */
		xUART1Signaling = false;
		/* Set infinite for receiver timer. */
		*_tmr_recv_uart1 = 0xFFFFFFFF;
		if(_datawidth8bitmore == true) {
			/* Update receiving buffer */
			uart_rx1_data_word = (volatile uint16_t *)_pbuf;
		}
		else {
			/* Update receiving buffer */
			uart_rx1_data_byte = (volatile uint8_t *)_pbuf;
		}
		uart1_wait_recv_frame = false;
		uart_rx1_nb_received = 0;
		_pRecvSize = (uint32_t *)&uart_rx1_nb_received;
		uart_rx1_nb_count = _size_t;
		datawidth1_is_bigger8bit = _datawidth8bitmore;

		if (rx_interrupt_is_used[_xPort] == true) {
			/* Set receiver timeout. */
			*_tmr_recv_uart1 = receive_timeout[1];
			_funcRecvSignaling1 = &prvRecvIssueSignal1;
			vTimer10msFuncReg(_funcRecvSignaling1, (void *)_tmr_recv_uart1);

			/* Enable Receive Interrupt. */
			UCSR1B |= (1 << RXCIE1);
		}
		else {
			*_tmr_recv_uart1 = receive_timeout[1];
			while(uart_rx1_nb_count && *_tmr_recv_uart1) {
				/* Wait incoming character. Do not block peripheral. */
				*_tmr_recv_uart1 = receive_timeout[1];
				while(!(UCSR1A & (1 << RXC1)) && *_tmr_recv_uart1);

				if (*_tmr_recv_uart1) {
					/* Check error receiving. */
					if(UCSR1A & 0x1C) {
						/* Clear receive buffer. */
						_data = UDR1;
					}
					else {
						/* Decrease remaining number data to receive. */
						uart_rx1_nb_count--;

						if(datawidth1_is_bigger8bit == true) {
							if(uart_rx1_data_word != NULL) {
								/* Get the data from receiver register. */
								_data = (UCSR1B & 0x02) >> 1;
								_data = _data << 8;
								_data = _data | (uint16_t)UDR1;
								/* Copy data to receiver buffer. */
								*uart_rx1_data_word = _data;
								/* Increase pointer of receiver data buffer. */
								uart_rx1_data_word++;
								/* Increase received word number. */
								uart_rx1_nb_received++;
							}
						}
						else {
							if(uart_rx1_data_byte != NULL) {
								/* Get the data from receiver register. */
								_data = UDR1;
								/* Copy data to receiver buffer. */
								*uart_rx1_data_byte = (uint8_t)_data;
								/* Increase pointer of receiver data buffer. */
								uart_rx1_data_byte++;
								/* Increase received byte number. */
								uart_rx1_nb_received++;
							}
						}
					}
				}
			}

			/* Release semaphore. */
			xUART1Semaphore = true;
			xUART1Signaling = true;
		}
	}
	else {
		return UART_ERR_INVALID_ARG;
	}

	return UART_STATUS_OK;
}

static void prvRecvIssueSignal0(void *_tmr)
{
	uint32_t *_ptr = _tmr;

	if((*_ptr == 0) && (uart0_wait_recv_frame == false)) {
		xUART0Signaling = true;
		uart0_wait_recv_frame = true;
	}
}

static void prvRecvIssueSignal1(void *_tmr)
{
	uint32_t *_ptr = _tmr;

	if((*_ptr == 0) && (uart0_wait_recv_frame == false)) {
		xUART1Signaling = true;
		uart0_wait_recv_frame = true;
	}
}

#endif /* BOARD_2_1_USED */
